package com.yanqu.road.server.gameplayer.module.disperseGold;

import com.yanqu.road.entity.disperseGold.DisperseGoldInfo;
import com.yanqu.road.entity.disperseGold.DisperseGoldRecord;
import com.yanqu.road.entity.disperseGold.GetDisperseGoldRewardResult;
import com.yanqu.road.entity.enums.eDisperseGoldStatus;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.log.LogDisperseReceive;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.logic.bussiness.player.UserDisperseGoldBussiness;
import com.yanqu.road.logic.pb.DisperseGoldPb;
import com.yanqu.road.pb.cross3.server.CrossChannelServerProto;
import com.yanqu.road.pb.disperseGold.DisperseGoldProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.manger.cross3.GameXServerNameMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.player.DisperseGoldMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

public class DisperseGoldModule extends GeneralModule {

    private final Object lockObject = new Object();

    public Object getLockObject() {
        return lockObject;
    }

    private Map<Long, DisperseGoldRecord> recordMap;

    public DisperseGoldModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        recordMap = UserDisperseGoldBussiness.getDisperseGoldRecordMap(player.getUserId());
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        recordMap.forEach((serverId, data)->{
            if (data.isInsertOption()) {
                UserDisperseGoldBussiness.addDisperseGoldRecord(data);
            } else if (data.isUpdateOption()) {
                UserDisperseGoldBussiness.updateDisperseGoldRecord(data);
            }
        });
        return true;
    }

    @Override
    public void loginSendMsg() {
        List<DisperseGoldInfo> infos = DisperseGoldMgr.sendDisperseGold(player.getUserId());
        if (infos == null) {
            return;
        }
        infos.sort(Comparator.comparingLong(DisperseGoldInfo::getDisperseId));

        synchronized (getLockObject()) {

            // 【发送送财】
            for (DisperseGoldInfo info : infos) {
                boolean send = true;         //是否需要发送散财数据
                Integer oldStatus = getDisperseGoldStatus(info.getServerId(), info.getServerId());
                if (oldStatus != null) {
                    send = false;
                }
                if (info.getServerId() != GameServer.getInstance().getServerId()) {//非本服数据，如果数据异常则不发
                    if (null == info.getUserBaseInfo()) {
                        send = false;
                    } else {
                        if (StringUtils.isNullOrEmpty(info.getUserBaseInfo().getNickName())) {
                            send = false;
                        }
                    }
                }
                if (send) {
                    //发送送财信息
                    UserBaseInfo userBaseInfo;
                    if (info.getServerId() == GameServer.getInstance().getServerId()) {//本服的玩家数据单独取
                        userBaseInfo = UserMgr.getUserBaseInfo(info.getUserId(), info.getServerId());
                    } else {
                        userBaseInfo = info.getUserBaseInfo();
                    }

                    syncDisperseMsg(DisperseGoldPb.parseDisperseGoldFindGodMsg(info, userBaseInfo));
                }
            }

            // 【清理无用数据】
            for (DisperseGoldRecord record : recordMap.values()) {
                for (Map.Entry<Long, Integer> entry : record.getDetailMap().entrySet()) {
                    Long disperseId = entry.getKey();
                    DisperseGoldInfo info = DisperseGoldMgr.getDisperseGoldInfo(disperseId);
                    if (info == null) {
                        record.getDetailMap().remove(disperseId);
                        record.setUpdateOption();
                    }
                }
            }
        }
    }

    /**
     * 记录散财信息（废弃）
     * @param serverId
     * @param disperseId
     */
    public void setRecord(long serverId, long disperseId) {
        DisperseGoldRecord record = recordMap.get(serverId);
        //添加送财记录
        if (record == null) {
            record = new DisperseGoldRecord(player.getUserId(), serverId, disperseId);
            record.setInsertOption();
            recordMap.put(serverId, record);
        } else if (disperseId > record.getDisperseId()){
            record.setDisperseId(disperseId);
        }
    }


    /**
     * 领取送财奖励
     */
    public GetDisperseGoldRewardResult getDisperseGoldReward(DisperseGoldInfo disperseGoldInfo) {
        GetDisperseGoldRewardResult result = new GetDisperseGoldRewardResult();
        synchronized (getLockObject()) {
            // 重复领奖判断
            Integer oldStatus = getDisperseGoldStatus(disperseGoldInfo.getServerId(), disperseGoldInfo.getDisperseId());
            if (oldStatus != null && oldStatus == eDisperseGoldStatus.GetReward.getValue()) {
                result.setRet(GameErrorCode.E_DISPERSEGOLD_REPEATED_REWARD);
                return result;
            }

            // 设置领奖状态
            updateDisperseGoldStatus(disperseGoldInfo.getServerId(), disperseGoldInfo.getDisperseId(), eDisperseGoldStatus.GetReward);

            // 领奖
            Property property = DisperseGoldMgr.getDisperseGoldReward(disperseGoldInfo, player.getUserInfo().getEarnSpeed());
            if (property != null) {
                player.getModule(CurrencyModule.class).addCurrency(property, eLogMoneyType.DisperseGold, eLogMoneyType.DisperseGoldReward);
            }
            result.setReward(PropertyHelper.parsePropertyToString(property));
        }
        return result;
    }

    /**
     * 获取散财记录（按区服）
     */
    public DisperseGoldRecord getRecord(long fromServerId) {
        if (!recordMap.containsKey(fromServerId)) {
            synchronized (getLockObject()) {
                if (!recordMap.containsKey(fromServerId)) {
                    DisperseGoldRecord record = new DisperseGoldRecord(getUserId(), fromServerId, 0);
                    record.setInsertOption();
                    recordMap.put(fromServerId, record);

                }
            }
        }
        return recordMap.get(fromServerId);
    }

    /**
     * 获取散财状态
     *
     * @return eDisperseGoldStatus的value，null表示没有这条送财的记录
     */
    public Integer getDisperseGoldStatus(long fromServerId, long disperseId) {
        DisperseGoldRecord record = getRecord(fromServerId);
        return record.getDetailMap().get(disperseId);
    }

    /**
     * 修改送财状态
     *
     * @return 修改成功
     */
    public boolean updateDisperseGoldStatus(long serverId, long disperseId, eDisperseGoldStatus status) {
        synchronized (getLockObject()) {
            DisperseGoldRecord record = getRecord(serverId);
            Map<Long, Integer> detailMap = record.getDetailMap();
            Integer oldStatus = detailMap.get(disperseId);
            // 【旧状态校验】
            if (oldStatus != null) {
                // 已领奖无法修改
                if (oldStatus == eDisperseGoldStatus.GetReward.getValue()) {
                    return false;
                }
            }
            // 【修改状态】
            detailMap.put(disperseId, status.getValue());
            record.setUpdateOption();
            return true;
        }
    }

    /**
     * 同步送财消息
     */
    public void syncDisperseMsg(DisperseGoldProto.DisperseGoldFindGodMsg.Builder msg) {
        long fromServerId = msg.getPlayerInfo().getServerId();
        long disperseId = msg.getDisperseId();
        synchronized (getLockObject()) {
            Integer oldStatus = getDisperseGoldStatus(fromServerId, disperseId);
            if (oldStatus == null) {

                // 跨地区送财补充区服名称
                if (msg.getChannelId() != ServerListMgr.getChannelId(GameServer.getInstance().getServerId())) {
                    CrossChannelServerProto.ServerNameListMsg.Builder serverNameMsg = GameXServerNameMgr.getServerNameMap().getServerNameMsg(Collections.singletonList(fromServerId));
                    player.sendPacket(ClientProtocol.U_SYNC_CHANNEL_SERVER_NAME, serverNameMsg);
                }

                player.sendPacket(ClientProtocol.U_DISPERSEGOLD_FIND_GOD, msg);
                // 修改状态为已发送
                updateDisperseGoldStatus(fromServerId, disperseId, eDisperseGoldStatus.HadSend);
                AutoLogMgr.add(new LogDisperseReceive(player.getUserId(), disperseId, msg.getUserId(), fromServerId, ""));
            }
        }
    }
}
